using System;
using System.Collections;
using Sedna.Core.Common;
using Sedna.Core.Common.Objects.Navigation;
using Spring.Util;

namespace Sedna.Core.Controller
{
	public class ExecutionContext : IExecutionContext
    {
        #region Constants
        private const string INFRA_PREFIX="infrastructure";
        private const string CURRENT_SCOPE_PREFIX_KEY = ".CurrentScopePrefix";
        private const string ACTION_NAME_KEY = ".ActionName";
        private const string POST_BACK_SOURCE_CONTROL_KEY = ".PostBackSourceControl";
        private const string IS_POST_BACK_KEY = ".IsPostBack";
        private const string CURRENT_CONFIGURATION_KEY = ".CurrentConfiguration";
        private const string COMMAND_NAME_KEY = ".commandName";
        private const string COMMAND_ARGUMENT_KEY = ".commandArgument";
        #endregion





        private IScopePathParser scopePathParser;
        private ICallContext callContext;
		private IDictionary inner = new Hashtable();

        private string alertMessage;
        private string alertMessageKey;
	    
        public ExecutionContext(IScopePathParser scopePathParser)
        {
            this.scopePathParser = scopePathParser;
            callContext = new CallContext();
        }

	    /// <summary>
	    /// Avoid using this property in your actions. Use executionContext parameter instead.
	    /// </summary>
	    public static IExecutionContext Current
		{
			get
			{
				if (BasePage.Current != null)
				{
					return BasePage.Current.ExecutionContext;
				}

				return null;
			}			
		}
	    
	    public static IExecutionContext GetCurrent(string currentScopePrefix)
	    {            
	        IExecutionContext executionContext = ExecutionContext.Current;
            executionContext.CurrentScopePrefix = currentScopePrefix;
            return executionContext;
        }

        #region Properties

	    public string AlertMessageKey
	    {
	        get { return alertMessageKey; }
	        set { alertMessageKey = value; }
	    }

	    public string AlertMessage
	    {
	        get { return alertMessage; }
	        set { alertMessage = value; }
	    }

	    public string CurrentScopePrefix
        {
            get { return (string)inner[INFRA_PREFIX + CURRENT_SCOPE_PREFIX_KEY]; }
            set { inner[INFRA_PREFIX + CURRENT_SCOPE_PREFIX_KEY] = value; }
        }

        public ICallContext CallContext
        {
            get { return callContext; }
            set { callContext = value; }
        }
	    
        public string CommandArgument
		{
			get {return this[INFRA_PREFIX+COMMAND_ARGUMENT_KEY] as string;}
		}	

		public string CommandName
		{
			get {return this[INFRA_PREFIX+COMMAND_NAME_KEY] as string;}
		}

		public IConfiguration CurrentConfiguration
		{
			get {return this[INFRA_PREFIX+CURRENT_CONFIGURATION_KEY] as IConfiguration;}
		}

		public string PostBackSourceControl
		{
			get { return this[INFRA_PREFIX+POST_BACK_SOURCE_CONTROL_KEY] as string;}
		}

		public string ActionName
		{
			get {return this[INFRA_PREFIX + ACTION_NAME_KEY] as string;}
		}

		public bool IsPostBack
		{
			get
			{
			    object isPostBack = this[INFRA_PREFIX+IS_POST_BACK_KEY];
				return isPostBack!=null?(bool)isPostBack:false;
			}
        }

        #endregion

        #region Access methods

        public void SetToCurrentScope(string postfix, object value)
		{
			this[CurrentScopePrefix + "." + postfix] = value;
		}

		public object GetFromCurrentScope(string postfix)
		{
            return this[CurrentScopePrefix + "." + postfix];
		}

		
		public void ClearScopedValue(String key, Scope scope)
		{
			if (!StringUtils.IsNullOrEmpty(key))
			{
				SetScopedValue(key, null, scope);
			}
		}

		public void SetScopedValue(String key, Object value, Scope scope)
		{
		    scopePathParser.SetScopedValue(scope, key, value);
		}

		public Object GetScopedValue(String key, Scope scope)
		{
            return scopePathParser.GetScopedValue(scope, key);
        }

        public void SetPropertyValue(string path, object value)
        {
            scopePathParser.Parse(path).Value = value;
        }

        public object GetPropertyValue(string path)
        {
            object result = scopePathParser.Parse(path).Value;

            if (result is IValueWrapper)
            {
                return ((IValueWrapper)result).GetValue(typeof(object));
            }

            return result;
        }
	    
        #endregion

		#region inner IDictionary delegate

		public bool Contains(object key)
		{
			return inner.Contains(key);
		}

		public void Add(object key, object value)
		{
			inner.Add(key, value);
		}

		public void Clear()
		{
			inner.Clear();
		}

		public IDictionaryEnumerator GetEnumerator()
		{
			return inner.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable)inner).GetEnumerator();
		}

		public void Remove(object key)
		{
			inner.Remove(key);
		}

		public ICollection Keys
		{
			get { return inner.Keys; }
		}

		public ICollection Values
		{
			get { return inner.Values; }
		}

		public bool IsReadOnly
		{
			get { return inner.IsReadOnly; }
		}

		public bool IsFixedSize
		{
			get { return inner.IsFixedSize; }
		}

		public object this[object key]
		{
			get { return inner[key]; }
			set { inner[key] = value; }
		}

		public void CopyTo(Array array, int index)
		{
			inner.CopyTo(array, index);
		}

		public int Count
		{
			get { return inner.Count; }
		}

		public object SyncRoot
		{
			get { return inner.SyncRoot; }
		}

		public bool IsSynchronized
		{
			get { return inner.IsSynchronized; }
		}

		#endregion
	}
}
